﻿using System;

namespace Jacobi.ComponentModel.Decomposition
{
    /// <summary>
    /// A default implementation for a pipe.
    /// </summary>
    /// <typeparam name="T">The data type of the pipe.</typeparam>
    public partial class Pipe<T> : IPipe<T>
    {
        private BlockingQueue<T> _queue;

        /// <summary>
        /// Default ctor.
        /// </summary>
        public Pipe()
        {
            _queue = new BlockingQueue<T>();
            Consumer = new ConsumerPort(this);
            Producer = new ProducerPort(this);
        }

        /// <summary>
        /// Retrieves a consumer port to read data items from the pipe.
        /// </summary>
        public IConsumerPort<T> Consumer { get; private set; }


        /// <summary>
        /// Retrieves a producer port to write data items to the pipe.
        /// </summary>
        public IProducerPort<T> Producer { get; private set; }

        /// <summary>
        /// Reads one data item from the pipe.
        /// </summary>
        /// <returns>Never returns null or default.</returns>
        /// <remarks>The calling Thread is blocked until data becomes available.</remarks>
        protected virtual T Read()
        {
            return _queue.Dequeue();
        }

        /// <summary>
        /// Writes one data item to the pipe.
        /// </summary>
        /// <param name="data">The data to put onto the pipe.</param>
        protected virtual void Write(T data)
        {
            _queue.Enqueue(data);
        }

    }
}
